using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;


namespace KFGame
{

    /// <summary>
    /// 框架常用的事件名
    /// </summary>
    public class KFEEVENTS
    {
        /// <summary>
        /// 退出应用
        /// </summary>
        public const string KFE_APPLICATION_EXIT = "KFE_APPLICATION_EXIT";

        /// <summary>
        /// 打开第一个场景 可以在配置中设置
        /// </summary>
        public const string KFE_SCENE_FIRSTSCENE_OPEN = "KFE_SCENE_FIRSTSCENE_OPEN";

        /// <summary>
        /// 打开后台场景
        /// </summary>
        public const string KFE_SCENE_BACKVIEW_OPEN = "KFE_SCENE_BACKVIEW_OPEN";

        /// <summary>
        /// 关闭后台场景
        /// </summary>
        public const string KFE_SCENE_BACKVIEW_CLOSE = "KFE_SCENE_BACKVIEW_CLOSE";

        /// <summary>
        /// 打开主场景 可以在配置中设置
        /// </summary>
        public const string KFE_SCENE_MAINSCENE_OPEN = "KFE_SCENE_MAINSCENE_OPEN";

        /// <summary>
        /// 转到前一次打开的场景
        /// </summary>
        public const string KFE_SCENE_PREVIOUS_OPEN = "KFE_SCENE_PREVIOUS_OPEN";

        /// <summary>
        /// 显示信息
        /// </summary>
        public const string KFE_MESSAGE_SHOW = "KFE_MESSAGE_SHOW";


        /// <summary>
        /// 向上操作
        /// </summary>
        public const string KFE_EVENT_TO_UP = "KFE_EVENT_TO_UP";

        /// <summary>
        /// 向下操作
        /// </summary>
        public const string KFE_EVENT_TO_DOWN = "KFE_EVENT_TO_DOWN";

        /// <summary>
        /// 向左操作
        /// </summary>
        public const string KFE_EVENT_TO_LEFT = "KFE_EVENT_TO_LEFT";

        /// <summary>
        /// 向右操作
        /// </summary>
        public const string KFE_EVENT_TO_RIGHT = "KFE_EVENT_TO_RIGHT";
        /// <summary>
        /// 向右操作
        /// </summary>
        public const string KFE_EVENT_TO_OK = "KFE_EVENT_TO_OK";

        /// <summary>
        /// 统计票券
        /// KFEvent 对象，KFE_STATISTICS_TICKET为统计名称 status =1 是否纳入统计  valueInt=  统计的值
        /// </summary>
        public const string KFE_STATISTICS_TICKET = "KFE_STATISTICS_TICKET";
        /// <summary>
        /// 统计卡片
        /// KFEvent 对象，KFE_STATISTICS_CARD为统计名称 status =1 是否纳入统计  valueInt=  统计的值
        /// </summary>
        public const string KFE_STATISTICS_CARD = "KFE_STATISTICS_CARD";
        /// <summary>
        /// 统计投币
        /// KFEvent 对象，KFE_STATISTICS_COINT为统计名称 status =1 是否纳入统计  valueInt=  统计的值
        /// </summary>
        public const string KFE_STATISTICS_COINT = "KFE_STATISTICS_COINT";
        /// <summary>
        /// 统计任意内容
        /// KFEvent 对象，tag标签为统计名称 status =1 是否纳入统计  valueInt=  统计的值
        /// </summary>
        public const string KFE_STATISTICS_ANYTHING = "KFE_STATISTICS_ANYTHING";
    }


    /// <summary>
    /// 事件结构体
    /// </summary>
    public class KFEvent
    {
        //定义事件名字 可作识别码
        public string name = "kfevent";
        //标记 模拟simulation 实例entity
        public string tag = "simulation";

        //事件类别
        public string type = KFEventManager.TYPE_KFEVENT_GAME;
        //定义ID作为识别码
        public int id = 0;

        //模拟按钮状态， 0是弹起，1是按下
        public int status = 0;
        //模拟按钮值
        public string keyCode;

        //源数
        public ArrayList datas = new ArrayList();
        //带数据
        public int valueInt = 0;
        public float valufloat = 0.0f;
        public string valueString = null;
        public System.Object value;

        public bool isEntity()
        {
            return tag == "entity";
        }

        public bool isKey(string code)
        {
            return keyCode == code;
        }

        public bool isEvent(string n)
        {
            return name == n;
        }
        public bool isID(int i)
        {
            return id == i;
        }

        public KFEvent(string n = null)
        {
            if (n != null)
                name = n;
        }
        public KFEvent(string n, string ntype)
        {
            if (n != null)
                name = n;

            if (ntype != null)
                type = ntype;
        }

        /// <summary>
        /// 事件包含关键字
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool eventContains(string key)
        {
            return name.Contains(key);
        }

    }


    /// <summary>
    /// 事件管理器，通过硬新数据转成事件，模拟数据转成事件，键盘鼠标等事件转成事件
    /// 统一事件到框架中，业务事件以事件驱动，与实际硬件无关，采用偶合对接
    /// 
    ///分类事件管理类型，常用类型， TYPE_KFEVENT_DEFAULT TYPE_KFEVENT_GAME TYPE_KFEVENT_CUSTOM
    /// 实制使用过程中可以通过用户自己定义类型
    /// 加速分发事件处理任务，当需要独立处理事件，又不让别的侦听器侦听到，就可以自定义类别
    /// 
    /// </summary>
    [DisallowMultipleComponent]
    public class KFEventManager : MonoBehaviour
    {

        /// <summary>
        /// 默认 由KF框架 使用  侦听框架事件
        /// </summary>
        public const string TYPE_KFEVENT_DEFAULT = "KFE_TYPE_DEFAULT";
        /// <summary>
        /// 游戏事件  游戏中使用事件
        /// </summary>
        public const string TYPE_KFEVENT_GAME = "KFE_TYPE_KFEVENT_GAME";
        /// <summary>
        /// 自定义  由用户自定义分类的，除了这个名字 可以注册定义自己的分类名称，
        /// 在侦听时需要使用相同的名称就可侦听到
        /// </summary>
        public const string TYPE_KFEVENT_CUSTOM = "KFE_TYPE_KFEVENT_CUSTOM";
        /// <summary>
        /// 所有类型  侦听是可以侦听所有事件产生
        /// </summary>
        public const string TYPE_KFEVENT_ALL = "KFE_TYPE_KFEVENT_ALL";




        private static KFEventManager eventManager = null;


        /// <summary>
        /// 侦听者
        /// </summary>
        /// <typeparam name="IKFEvent"></typeparam>
        /// <returns></returns>
        private static List<IKFEvent> listenors = new List<IKFEvent>();

        /// <summary>
        /// 添加侦听者
        /// </summary>
        /// <param name="e"></param>
        public static void addListor(IKFEvent e)
        {
            listenors.Add(e);
        }

        /// <summary>
        /// 移除侦者
        /// </summary>
        /// <param name="e"></param>
        public static void removeListor(IKFEvent e)
        {
            listenors.Remove(e);
        }

        /// <summary>
        /// 全局化实例对象
        /// </summary>
        /// <returns></returns>
        public static KFEventManager Instantiation()
        {
            if (eventManager == null)
            {
                //实例框架，防止单独使用
                eventManager = KF.kf.kfevents;
                return eventManager;
            }
            return eventManager;
        }


        public delegate void PopEvent(KFEvent e);


        /// <summary>
        /// 侦器集
        /// </summary>
        /// <typeparam name="string"></typeparam>
        /// <typeparam name="PopEvent"></typeparam>
        /// <returns></returns>
        public Dictionary<string, PopEvent> listeners = new Dictionary<string, PopEvent>();

        //事件队列
        private Stack<KFEvent> events = new Stack<KFEvent>();
        static System.Object locker = new System.Object();


        /// <summary>
        /// 通过注册事件管理 
        /// 在实制开发中可以通过打印查找事是否有应用
        /// </summary>
        /// <typeparam name="string"></typeparam>
        /// <returns></returns>
        public static List<string> RegisterEventList = new List<string>();

        /// <summary>
        /// 注册事件
        /// </summary>
        /// <param name="name"></param>
        public static void RegisterEvent(string name)
        {
            if (!RegisterEventList.Contains(name))
                RegisterEventList.Add(name);
        }

        /// <summary>
        /// 添加侦听
        /// </summary>
        /// <param name="e"></param>
        /// <param name="type"></param>
        public void addLisener(PopEvent e, string type = TYPE_KFEVENT_GAME)
        {
            if (type == TYPE_KFEVENT_ALL)
            {
                foreach (var val in listeners.Keys)
                    if (!isListener(val, e))
                        listeners[val] += e;
                return;
            }

            if (listeners.ContainsKey(type))
            {
                if (!isListener(type, e))
                    listeners[type] += e;
                return;
            }

            listeners.Add(type, e);
        }

        /// <summary>
        /// 侦听代理是否己添加
        /// </summary>
        /// <param name="type"></param>
        /// <param name="pop"></param>
        /// <returns></returns>
        public bool isListener(string type, PopEvent pop)
        {
            if (!listeners.ContainsKey(type))
                return false;
            if (listeners == null) return false;
            if (listeners[type] == null) return false;

            System.Delegate[] list = listeners[type].GetInvocationList();
            return System.Array.IndexOf(list, pop) > -1;
        }




        /// <summary>
        /// 移除事件的所有侦听
        /// </summary>
        /// <param name="e"></param>
        public void removeAllListenerForEvent(PopEvent e)
        {
            foreach (var val in listeners.Keys)
                if (isListener(val, e))
                    listeners[val] -= e;
        }

        /// <summary>
        /// 移移侦听
        /// </summary>
        /// <param name="e"></param>
        /// <param name="type"></param>
        public void removeListener(PopEvent e, string type = TYPE_KFEVENT_GAME)
        {
            if (type == TYPE_KFEVENT_ALL)
            {
                removeAllListenerForEvent(e);
                return;
            }


            if (isListener(type, e))
                listeners[type] -= e;


        }

        ///清空侦听器
        public void cleanListener(string type)
        {

            if (type == TYPE_KFEVENT_ALL)
            {
                foreach (var val in listeners.Keys)
                    listeners[val] = null;
                return;
            }

            if (listeners.ContainsKey(type))
                listeners[type] = null;

        }

        /// <summary>
        /// 发出事件
        /// </summary>
        /// <param name="e"></param>
        public void Pop(KFEvent e)
        {

            foreach (var it in listenors)
                if (it.OnKFEvent(e.type, e))
                    return;

            if (listeners.ContainsKey(e.type))
                listeners[e.type](e);

        }

        /// <summary>
        ///添加事件
        /// </summary>
        /// <param name="v"></param>
        public void push(KFEvent v)
        {

            lock (locker)//加锁
                events.Push(v);
        }

        /// <summary>
        /// 主线程运行
        /// </summary>
        void Update()
        {
            if (events.Count > 0)
            {
                lock (locker)
                    while (events.Count > 0)
                        Pop(events.Pop());
            }
        }


    }

}